<template>
  <div class="award">
    <transition :enter-active-class="animateShowIn">
      <person-dialog class="animated" v-if="showPersonDialog"></person-dialog>
    </transition>
    <div ref="container" class="animate-person"></div>
  </div>
</template>

<script>
import * as THREE from 'three'
import * as TWEEN from 'tween'
import { CSS3DObject, CSS3DRenderer } from '@/common/js/css3drenderer'
import PersonDialog from '@/components/PersonDialog'

const animateIn = [
  'bounceIn',
  'bounceInDown',
  'bounceInLeft',
  'bounceInRight',
  'bounceInUp',
  'fadeIn',
  'fadeInDown',
  'fadeInDownBig',
  'fadeInLeft',
  'fadeInLeftBig',
  'fadeInRight',
  'fadeInRightBig',
  'fadeInUp',
  'fadeInUpBig',
  'rotateIn',
  'rotateInDownLeft',
  'rotateInDownRight',
  'rotateInUpLeft',
  'rotateInUpRight',
  'slideInDown',
  'slideInLeft',
  'slideInRight'
]
export default {
  name: 'Award',
  components: {
    PersonDialog
  },
  data () {
    return {
      peopleData: [],
      peopleShowData: [],
      camera: null,
      scene: null,
      renderer: null,
      targets: { table: [], sphere: [], helix: [], grid: [], gridAward: [] },
      showPersonDialog: false,
      curPersonNum: 0,
      anmiateStart: null,
      isAnimate: false,
      animateShowIn: '',
      clearTime: null,
      clearTimeChange: null,
      stopAnimate: null
    }
  },
  mounted () {
    this.totalPerson()
    this.animateImg()
    this.animate()
    this.showPersonCome()
    document.onkeydown = e => {
      if (this.$route.name === 'Award') {
        switch (e.keyCode) {
          case 13: // ENTER键开始抽奖
            if (!this.isAnimate) {
              clearTimeout(this.clearTimeChange)
              clearInterval(this.clearTime)
              this.showPersonDialog = false
              this.startAward()
            }
            break
          case 32: // 空格键切换到中奖人页面
            if (this.isAnimate) {
              this.$router.push({ name: 'GetAward' })
            }
            break
          case 68: // D键切换到弹幕界面
            this.$router.push({ name: 'barrage' })
        }
      }
    }
  },
  beforeDestroy () {
    TWEEN.removeAll()
    clearTimeout(this.clearTimeChange)
    clearInterval(this.clearTime)
    window.removeEventListener('resize', this.onWindowResize)
    window.cancelAnimationFrame(this.stopAnimate)
  },
  beforeRouteEnter (to, from, next) {
    if (from.name === 'barrage' && to.name === 'Award') {
      next(vm => {
        vm.$router.go(0)
      })
    } else {
      next()
    }
  },
  methods: {
    totalPerson () {
      let row = 1
      let col = 1
      for (let i = 0; i < 168; i++) {
        let people = {}
        people.Headimgurl = '../../static/imgs/1.jpg'
        people.p_x = col++
        people.p_y = row
        this.peopleData.push(people)
        if (col > 18) {
          col = 1
          row++
        }
      }
    },
    animateImg () {
      this.camera = new THREE.PerspectiveCamera(
        50,
        window.innerWidth / window.innerHeight,
        1,
        10000
      )
      this.camera.position.z = 2800
      this.scene = new THREE.Scene()
      this.createTable()
      this.createSphere()
      this.createHelix()
      this.createGrid()
      this.createGirdAward()
      this.renderer = new CSS3DRenderer()
      this.renderer.setSize(window.innerWidth, window.innerHeight)
      this.renderer.domElement.style.position = 'absolute'
      this.$refs.container.appendChild(this.renderer.domElement)
      let ini = 0
      this.anmiateStart = setInterval(() => {
        ini = ini >= 4 ? 0 : ini
        ++ini
        switch (ini) {
          case 1:
            this.transform(this.targets.sphere, 2000)
            break
          case 2:
            this.transform(this.targets.helix, 2000)
            break
          case 3:
            this.transform(this.targets.grid, 2000)
            break
          case 4:
            this.transform(this.targets.table, 2000)
            break
        }
      }, 4000)
      this.transform(this.targets.grid, 2000)
      window.addEventListener('resize', this.onWindowResize, false)
    },
    createTable () {
      this.peopleData.forEach(item => {
        let element = document.createElement('div')
        element.className = 'element'
        element.style.backgroundColor =
          'rgba(0,127,127,' + (Math.random() * 0.5 + 0.25) + ')'

        let img = document.createElement('img')
        img.src = item.Headimgurl
        element.appendChild(img)

        let object = new CSS3DObject(element)
        object.position.x = Math.random() * 4000 - 2000
        object.position.y = Math.random() * 4000 - 2000
        object.position.z = Math.random() * 4000 - 2000

        this.scene.add(object)
        this.peopleShowData.push(object)

        let object1 = new THREE.Object3D()
        object1.position.x = item.p_x * 140 - 1530
        object1.position.y = -(item.p_y * 180) + 990
        this.targets.table.push(object1)
      })
    },
    createSphere () {
      let vector = new THREE.Vector3()
      for (let i = 0, l = this.peopleShowData.length; i < l; i++) {
        let phi = null
        let theta = null
        phi = Math.acos(-1 + 2 * i / l)
        theta = Math.sqrt(l * Math.PI) * phi
        let object = new THREE.Object3D()

        object.position.x = 800 * Math.cos(theta) * Math.sin(phi)
        object.position.y = 800 * Math.sin(theta) * Math.sin(phi)
        object.position.z = 800 * Math.cos(phi)

        vector.copy(object.position).multiplyScalar(2)
        object.lookAt(vector)
        this.targets.sphere.push(object)
      }
    },
    createHelix () {
      let vector = new THREE.Vector3()
      for (let i = 0, l = this.peopleShowData.length; i < l; i++) {
        let phi = i * 0.175 + Math.PI

        let object = new THREE.Object3D()

        object.position.x = 900 * Math.sin(phi)
        object.position.y = -(i * 8) + 850
        object.position.z = 900 * Math.cos(phi)

        vector.x = object.position.x * 2
        vector.y = object.position.y
        vector.z = object.position.z * 2

        object.lookAt(vector)
        this.targets.helix.push(object)
      }
    },
    createGrid () {
      for (let i = 0; i < this.peopleShowData.length; i++) {
        let object = new THREE.Object3D()
        object.position.x = (i % 5) * 400 - 1200
        object.position.y = -(Math.floor(i / 5) % 5) * 400 + 800
        object.position.z = Math.floor(i / 25) * 500 - 1000
        this.targets.grid.push(object)
      }
    },
    createGirdAward () {
      let vector = new THREE.Vector3()
      for (let i in this.peopleShowData) {
        let obj = new THREE.Object3D()
        obj.position.x = (i % 5) * 600 - 1200
        obj.position.y = -(Math.floor(i / 5) % 5) * 400 + 800
        obj.position.z = 200 - i * 60 * 1.5
        // obj.rotation.z = -i * 0.03

        vector.x = obj.position.x
        vector.y = obj.position.y
        vector.z = obj.position.z

        obj.lookAt(vector)
        this.targets.gridAward.push(obj)
      }
    },
    transform (targets, duration, award) {
      TWEEN.removeAll()
      for (let i = 0; i < this.peopleShowData.length; i++) {
        let object = this.peopleShowData[i]
        let target = targets[i]
        if (award) {
          new TWEEN.Tween(object.position)
            .to(
              {
                x: target.position.x,
                y: target.position.y,
                z: target.position.z
              },
              2500
            )
            .easing(TWEEN.Easing.Exponential.InOut)
            .start()
        } else {
          new TWEEN.Tween(object.position)
            .to(
              {
                x: target.position.x,
                y: target.position.y,
                z: target.position.z
              },
              Math.random() * duration + duration
            )
            .easing(TWEEN.Easing.Exponential.InOut)
            .start()
        }
        new TWEEN.Tween(object.rotation)
          .to(
            {
              x: target.rotation.x,
              y: target.rotation.y,
              z: target.rotation.z
            },
            Math.random() * duration + duration
          )
          .easing(TWEEN.Easing.Exponential.InOut)
          .start()
      }
      new TWEEN.Tween(this)
        .to({}, 1000000)
        .onUpdate(this.render)
        .start()
    },
    onWindowResize () {
      this.camera.aspect = window.innerWidth / window.innerHeight
      this.camera.updateProjectionMatrix()
      this.renderer.setSize(window.innerWidth, window.innerHeight)
    },
    animate () {
      this.stopAnimate = requestAnimationFrame(this.animate)
      TWEEN.update()
    },
    render () {
      if (this.isAnimate) {
        this.scene.rotation.y = 0
        for (let i = 0; i < this.peopleShowData.length; i++) {
          let obj = this.peopleShowData[i]
          obj.position.z += 180
          if (obj.position.z > 800) {
            obj.position.z = 200 - (this.peopleShowData.length - 1) * 60 * 1.5
          }
        }
      } else {
        this.scene.rotation.y += 0.018
      }
      this.renderer.render(this.scene, this.camera)
    },
    startAward () {
      clearInterval(this.anmiateStart)
      this.isAnimate = true
      this.transform(this.targets.gridAward, 1000, true)
    },
    showPersonCome () {
      this.clearTime = setInterval(() => {
        let randIn = parseInt(Math.random() * animateIn.length, 10)
        this.animateShowIn = animateIn[randIn]
        if (this.curPersonNum >= this.peopleData.length) {
          this.curPersonNum = 0
        }
        this.showPersonDialog = true
        this.clearTimeChange = setTimeout(() => {
          let img = document
            .getElementsByClassName('element')[this.curPersonNum].getElementsByTagName('img')[0]
          img.setAttribute('src', '../../static/imgs/b.png')
          this.curPersonNum++
          this.showPersonDialog = false
        }, 3000)
      }, 4500)
    }
  }
}
</script>

<style lang='less'>
.award {
  .animate-person {
    .element {
      width: 120px;
      height: 120px;
      box-shadow: 0px 0px 12px rgba(0, 255, 255, 0.5);
      border: 1px solid rgba(127, 255, 255, 0.25);
      cursor: default;
      img {
        position: absolute;
        border: none;
        border-radius: 15px;
        width: 100%;
        height: 100%;
      }
    }
  }
}
</style>
